package com.nebrija.riif.model.resolver;

import com.nebrija.riif.model.RIIFPropertiesContainer;
import com.nebrija.riif.model.Util;

public class LogicalResolver {
	
	public static final String EQUALS="==";
	public static final String LESS_EQUAL = "<=";
	public static final String GT_EQUAL = ">=";
	public static final String DIFFERENT = "!=";
	public static final String LESS_THAN = "<";
	public static final String GT_THAN = ">";
	
	public Object resolveCondition(Object o1, Object o2, String op){
		
		// If numeric comparison, normalize everything to Double
		if(o1 instanceof Number && o2 instanceof Number 
				&& o1.getClass().getName()!=o2.getClass().getName()){
			o1 = ((Number)o1).doubleValue();
			o2 = ((Number)o2).doubleValue();
		}
		
		if(op.equals(EQUALS)){
			if (o1==o2 || o1.equals(o2)){
				return Boolean.TRUE;
			}
			//TODO What if we need to compare 2 strings?
			if(o1 instanceof String || o2 instanceof String){
				return o1.toString()+EQUALS+o2.toString();
			}

			if(o1 instanceof Long || o1 instanceof Integer || o1 instanceof Float){
				
			}
			
			return Boolean.FALSE;			
		}
		
		if (op.equals(DIFFERENT)){
			if (o1==o2 || o1.equals(o2)){
				return Boolean.FALSE;
			}
			//TODO What if we need to compare 2 strings?
			if(o1 instanceof String || o2 instanceof String){
				return o1.toString()+DIFFERENT+o2.toString();
			}
			
			return Boolean.TRUE;			
		}
		
		// <, >, >= or <= will not be used with strings.
		if(o1 instanceof String || o2 instanceof String){
			return o1.toString()+op+o2.toString();
		}	
		
		@SuppressWarnings("rawtypes")
		Comparable compareX = (Comparable) o1;
		@SuppressWarnings("unchecked")
		int value = compareX.compareTo(o2);
		if(op.equals(LESS_EQUAL)){
			return(value<=0)?Boolean.TRUE:Boolean.FALSE;
		}
		if(op.equals(GT_EQUAL)){
			return(value>=0)?Boolean.TRUE:Boolean.FALSE;
		}	
		if(op.equals(LESS_THAN)){
			return(value<0)?Boolean.TRUE:Boolean.FALSE;
		}
		if(op.equals(GT_THAN)){
			return(value>0)?Boolean.TRUE:Boolean.FALSE;
		}		
		return (o1.toString()+op+o2.toString());
	}
	
	public Object resolve(String formula, RIIFPropertiesContainer c){
		int index=formula.indexOf(EQUALS);
		int size=2;
		String op = EQUALS;
		if (index==-1){
			index= formula.indexOf(LESS_EQUAL);
			op=LESS_EQUAL;
		}
		if (index==-1){
			index= formula.indexOf(GT_EQUAL);
			op=GT_EQUAL;
			
		}
		if (index==-1){
			index= formula.indexOf(DIFFERENT);
			op=DIFFERENT;
		}
		if (index==-1){
			size=1;
			index= formula.indexOf(LESS_THAN);
			op=LESS_THAN;
		}
		if (index==-1){
			index= formula.indexOf(GT_THAN);
			op=GT_THAN;
		}
		if (index==-1){
			if(formula.equalsIgnoreCase("false") || formula.equalsIgnoreCase("true")){
				return Boolean.parseBoolean(formula);
			}
			return formula;
		}
		String pre = formula.substring(0,index);
		String post = formula.substring(index+size);
		
		Object o1 = Util.resolveFormula(pre, c);
		Object o2 = Util.resolveFormula(post, c);

		return resolveCondition(o1, o2, op);
	}
	

}
